#include "GAF_Effect.h"

namespace GAF
{
	Effect::Effect()
	{
		m_nGType		= GRAPHICS_EFFECT;

		ATTRIB(Step)		= 0;
		ATTRIB(Reverse)		= false;
		m_ERK			= RES_UNKNOW;
		m_hFrame		= NULL;
		m_nStartID		= 0;
		m_nEndID		= 0;
		m_rClips		= NULL;
		m_pPackage		= NULL;
		m_hImage		= NULL;
		m_nStartFm		= 0;
		m_nEndFm		= 0;
		m_nCurFm		= 0;
		m_ttExtra		= 0;
	}

	Effect::~Effect()
	{
		GAF_DELETE(m_rClips);
	}

	bool Effect::Init(Bundle* pbdlParam)
	{
		return OnInit(pbdlParam);
	}

	bool Effect::Init(Package* pPackage, const UINT nStartID, const int nEndID, Bundle* pbdlParam)
	{
		if(!Reset(pPackage, nStartID, nEndID))
			return false;
		return OnInit(pbdlParam);
	}

	bool Effect::Init(Image* pImage, const UINT nWidthNum, const UINT nHeightNum, const UINT nFrameNum, Bundle* pbdlParam)
	{
		if(!Reset(pImage, nWidthNum, nHeightNum, nFrameNum))
			return false;
		return OnInit(pbdlParam);
	}

	void Effect::PlayTo(UINT nToFrame)
	{
		if(ATTRIB(Reverse) == false)
			PlayFree(m_nStartID, nToFrame, ATTRIB(Loop), false);
		else
			PlayFree(nToFrame, m_nEndID, ATTRIB(Loop), true);
	}

	void Effect::PlayFree(UINT nStartFrame, UINT nEndFrame, bool isLoop, bool isReverse)
	{
		m_Param.PutInteger(GAF_PRM_EFFECT_START_i, nStartFrame);
		m_Param.PutInteger(GAF_PRM_EFFECT_END_i, nEndFrame);
		m_Param.PutBoolean(GAF_PRM_EFFECT_LOOP_b, isLoop);
		m_Param.PutBoolean(GAF_PRM_EFFECT_REVERSE_b, isReverse);

		Play(&m_Param);
	}

	bool Effect::Reset(Package* pPackage, const UINT nStartID, const int nEndID)
	{
		GAF_CHECK_R(pPackage != NULL, false);

		int _nEndID = nEndID;
		if(_nEndID < 0)
			_nEndID = pPackage->GetCount() - 1;

		m_pPackage = pPackage;
		m_nStartID = nStartID;
		m_nEndID = _nEndID;
		m_nCurFm = m_nStartID;

		m_ERK = RES_PACKAGE;

		// 检查包资源，并加载第一帧图像
		LoadPkgFrame(m_nStartID);
		if(m_hFrame == NULL)
		{
			return false;
		}

		return true;
	}

	bool Effect::Reset(Image* pImage, const UINT nWidthNum, const UINT nHeightNum, const UINT nFrameNum)
	{
		GAF_CHECK_R(pImage != NULL, false);

		m_hImage = pImage->GetImageHandle();

		m_nStartID = 0;
		m_nEndID = GAF_MATH_MIN(nWidthNum * nHeightNum, nFrameNum);
		m_rClips = GAF_NEW_ARY(Rect, m_nEndID);

		ATTRIB(Size).nWidth = pImage->GetSize_a().nWidth / nWidthNum;
		ATTRIB(Size).nHeight = pImage->GetSize_a().nHeight / nHeightNum;
		for(int i = 0; i < (int)m_nEndID; i++)
		{
			m_rClips[i].Set(
				ATTRIB(Size).nWidth * (i % nWidthNum),
				ATTRIB(Size).nHeight * (i / nWidthNum),
				ATTRIB(Size).nWidth,
				ATTRIB(Size).nHeight);
		}

		m_ERK = RES_IMAGE;
		return true;
	}

	UINT Effect::GetStartFrame()
	{
		return m_nStartFm;
	}

	UINT Effect::GetEndFrame()
	{
		return m_nEndFm;
	}

	UINT Effect::GetFrameCount()
	{
		return m_nEndFm - m_nStartFm + 1;
	}

	UINT Effect::GetAllFrameCount()
	{
		return m_nEndID - m_nStartID + 1;
	}

	void Effect::SetFrame(UINT nFrameID)
	{
		GAF_CHECK(GetState_a() == PLAYER_STOP);

		m_nCurFm = nFrameID + m_nStartID;
		if(m_ERK == RES_PACKAGE)
		{
			if(m_nCurFm < m_nStartID || m_nCurFm > m_nEndID)
				m_nCurFm = m_nStartID;

			LoadPkgFrame(m_nCurFm);
		}
		else if(m_ERK == RES_IMAGE)
		{
			if(m_nCurFm >= m_nEndID)
				m_nCurFm = 0;
		}

	}

	void Effect::AddStep()
	{
		ATTRIB(Step)++;
	}

	bool Effect::Playing(Bundle* pbdlParam)
	{
		if(m_ERK == RES_PACKAGE)
			GAF_CHECK_R(m_pPackage != NULL, false);

		if(pbdlParam != NULL)
		{
			m_nStartFm = pbdlParam->GetInteger(GAF_PRM_EFFECT_START_i);
			m_nEndFm = pbdlParam->GetInteger(GAF_PRM_EFFECT_END_i);
			ATTRIB(Loop) = pbdlParam->GetBoolean(GAF_PRM_EFFECT_LOOP_b);
			ATTRIB(Reverse) = pbdlParam->GetBoolean(GAF_PRM_EFFECT_REVERSE_b);
		}
		else
		{
			m_nStartFm = m_nStartID;
			m_nEndFm = m_nEndID;
		}

		//		CF
		//		|
		//		V
		// SID------SF==========EF-----EID

		if(m_nStartFm < m_nStartID)
			m_nStartFm = m_nStartID;
		if(m_nEndFm > m_nEndID)
			m_nEndFm = m_nEndID;
		if(m_nStartFm >= m_nEndFm)
			return false;

		// 如果当前帧在区间之外
		if(m_nCurFm < m_nStartFm || m_nCurFm > m_nEndFm)
			m_nCurFm = m_nStartFm;

		// 根据正序反序，调整当前帧
		if(!ATTRIB(Reverse) && m_nCurFm == m_nEndFm)
			m_nCurFm = m_nStartFm;
		else if(ATTRIB(Reverse) && m_nCurFm == m_nStartFm)
			m_nCurFm = m_nEndFm;

		// 加载当前帧
		LoadPkgFrame(m_nCurFm);
		GAF_CHECK_R(m_hFrame != NULL, false);

		// 重置多余时间
		m_ttExtra = 0;

		return true;
	}

	bool Effect::Running(TimeTicks ttUsed, bool& isFinish)
	{
		if(ATTRIB(Reverse))
		{
			m_nCurFm -= GetUpdateFrame(ttUsed);

			if(m_nCurFm < m_nStartFm)
			{
				isFinish = true;
				m_nCurFm = m_nStartFm;
				if(GetLoop_a() == false)
				{
					return false;
				}
				m_nCurFm = m_nEndFm;
			}
		}
		else
		{
			m_nCurFm += GetUpdateFrame(ttUsed);

			if(m_nCurFm > m_nEndFm)
			{
				isFinish = true;
				m_nCurFm = m_nEndFm;
				if(GetLoop_a() == false)
				{
					return false;
				}
				m_nCurFm = m_nStartFm;
			}
		}

		LoadPkgFrame(m_nCurFm);

		if(m_hFrame == NULL)
			return false;

		return true;
	}

// 	bool Effect::OnUpdateReverse()
// 	{
// 		m_nCurFm -= GetUpdateFrame();
//
// 		if(m_nCurFm < m_nStartFm)
// 		{
// 			m_nCurFm = m_nStartFm;
// 			if(GetLoop_a() == false)
// 			{
// 				return false;
// 			}
// 			m_nCurFm = m_nEndFm;
// 		}
//
// 		return true;
// 	}

	ImageHandle Effect::GetFrameImageHandle()
	{
		return m_hFrame;
	}

	Rect Effect::GetClip_a()
	{
		if(m_ERK == RES_PACKAGE)
		{
			return GAF_RECT_NULL;
		}
		else if(m_ERK == RES_IMAGE)
		{
			return m_rClips[m_nCurFm];
		}
		else return GAF_RECT_NULL;
	}

	int Effect::GetUpdateFrame(TimeTicks ttUsed)
	{
		return 1;

		int _nUpdateFrame = (ttUsed + m_ttExtra) / GetInterval_a();
		m_ttExtra = (ttUsed + m_ttExtra) % GetInterval_a();

		return _nUpdateFrame;
	}

	void Effect::LoadPkgFrame(UINT nID)
	{
		if(m_ERK == RES_PACKAGE)
		{
			static char _szName[128];
			ImageInfo _ii;

			GAF_CHECK(m_pPackage != NULL);

			SYS_SPRINTF(_szName, "%d.bmp", nID);
			m_hFrame = m_pPackage->GetImageHandle(_szName, /*ATTRIB(Size).nWidth, ATTRIB(Size).nHeight, */_ii);
			SetSize(_ii.nWidth, _ii.nHeight);
		}
	}
}
